home *** CD-ROM | disk | FTP | other *** search
- /*
- * subsampleNI.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /* subsampleNI: program performs image size reduction, in particular
- * enabling non-integer subsampling
- */
-
- #define DFLTPCT 50.0 /* default subsample percentage */
-
- #define G_THRESHPCT_M 100.0 /* default gray thresh pct for matched fltr */
- #define G_THRESHPCT_R 100.0 /* default gray thresh pct for rect fltr */
- #define G_THRESHPCT_G 60.0 /* default gray thresh pct for Gaussian fltr */
-
- #define MAXCOEF 100.0 /* maximum filter coefficient value */
- #define RESOLUTION 8 /* subpixel res. of filter */
- #define FLTR_VAR_NUM 2.0 /* num. of var.s at max width of fltr */
-
- #define MAX_BITS_QUANT 8 /* max. bits of gray quantization */
-
- #define ABSF(A) ((A > 0.0) ? A:-(A)) /* floating absolute value */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <images.h>
- #include <tiffimage.h>
- #include <math.h>
- extern void print_sos_lic ();
-
- int shrinkGG (unsigned char **, long, long, unsigned char **, long *, long *,
- double, long, double, double);
- long usage (short);
- long input (int, char **, double *, long *, long *, long *, double *,
- double *, short *, short *);
-
- int argc;
- char *argv[];
- double *pct; /* subsample percentage */
- long *wSize, *hSize; /* subsampled image size: width, height */
- long *fltrSize; /* filter sidelength */
- double *fltrVarNum; /* num. of var.s at max width of fltr */
- double *threshG; /* gray-scale threshold scale factor */
- short *qfFlag; /* quick filter if =1, or default if 0 */
- short *gfFlag; /* Gaussian filter if =1, or default if 0 */
-
- main (
- int argc,
- char *argv[])
- {
- Image *imgI, *imgO; /* I/O image structures */
- unsigned char **imgIn, **imgGray; /* input and gray images */
- long widthIn, heightIn; /* image size */
- long widthOut, heightOut;
- long fltrSize; /* sidelength of filter */
- long xSize, ySize; /* subsampled image size */
- double pct, /* percentage of row/cols to remain */
- rate, /* subsample rate */
- xRate, yRate, /* rate to reach desired size */
- threshG, /* gray-scale threshold scale factor */
- fltrVarNum, /* num of var.s at max width of fltr */
- fltrVar; /* variance of Gaussian filter [pix] */
- short qfFlag; /* quick filter if =1, or dflt */
- short gfFlag; /* quick filter if =1, or dflt */
-
- if (input (argc, argv, &pct, &xSize, &ySize, &fltrSize,
- &fltrVarNum, &threshG, &qfFlag, &gfFlag) < 0)
- return (-1);
-
- /* allocate input image memory */
- imgI = ImageIn (argv[1]);
- imgIn = ImageGetPtr (imgI);
- heightIn = ImageGetHeight (imgI);
- widthIn = ImageGetWidth (imgI);
-
- /* set threshold contrast factors depending on slow/quick */
- if (threshG == -1.0) {
- if (qfFlag == 1)
- threshG = G_THRESHPCT_R;
- else if (gfFlag == 1)
- threshG = G_THRESHPCT_G;
- else
- threshG = G_THRESHPCT_M;
- }
- threshG = threshG / 100.0;
-
- /* determine subsampling rate, filter parameters */
- if (xSize == -1 && ySize == -1)
- rate = 100.0 / pct;
- else {
- xRate = (double) widthIn / (double) xSize;
- yRate = (double) heightIn / (double) ySize;
- if (xRate > yRate)
- rate = xRate;
- else
- rate = yRate;
- if (rate < 1.0)
- rate = 1.0;
- pct = 100.0 / rate;
- }
- if (fltrSize == 0)
- fltrSize = 2 * (long) ((100.0 / pct - 1.0) / 2.0 + 0.9999) + 1;
- if (fltrSize % 2 == 0)
- fltrSize += 1;
- fltrVar = ((double) (fltrSize - 1)) / (2.0 * fltrVarNum);
- if (fltrVar == 0.0)
- fltrVar = 1.0;
-
- /* determine output size and allocate output image */
- heightOut = (long) ((heightIn - fltrSize) / rate) + 1;
- widthOut = (long) ((widthIn - fltrSize) / rate) + 1;
- imgO = ImageAlloc (heightOut, widthOut, 8);
- imgGray = ImageGetPtr (imgO);
- printf ("Image input size = %dx%d, filter size = %dx%d\n",
- widthIn, heightIn, fltrSize, fltrSize);
-
- /* perform subsampling */
- shrinkGG (imgIn, widthIn, heightIn, imgGray, &widthOut, &heightOut,
- pct, fltrSize, threshG, fltrVar);
-
- /* write output image to file */
- ImageOut (argv[2], imgO);
-
- printf ("Image output size = %dx%d\n", widthOut, heightOut);
-
- return (0);
- }
-
- /* SHRINKGG: shrink program for gray-scale input image uses Gaussian filter
- */
-
- int
- shrinkGG (imgIn, widthIn, heightIn, imgOut, widthOut, heightOut,
- pct, fltrSize, threshG, fltrVar)
- unsigned char **imgIn, **imgOut; /* input and output images */
- long widthIn, heightIn;
- long *widthOut, *heightOut;
- double pct; /* percentage of row/cols to remain */
- long fltrSize; /* sidelength of filter */
- double threshG; /* gray-scale threshold scale factor */
- double fltrVar; /* variance of Gaussian filter [pix] */
- {
- long halfFltr, /* half filter sidelength */
- xOut, yOut; /* output image coord.s */
-
- long temp; /* value of pixel before normaliz. */
- long xMinW, xMaxW, /* min and max window coord.s */
- yMaxW, yMinW;
- double xIn, yIn; /* input image subpixel coord.s */
- long xInMid, yInMid; /* integer middle of fltr on input */
- double rate; /* subsample rate */
- long **coef; /* fltr coefs for (res * size) dists */
- long halfCoef, /* no. coef.s in half filter */
- halfCoefPHalf; /* no. coef.s in half plus half fltr */
- double exponent; /* exponent of Gaussian for filter */
- long sum, /* result of filter conv. at pt */
- sumCoef; /* sum of coef.s applied at point */
- struct point end; /* bottom right of image */
- double endYMHalf, endXMHalf; /* last x,y coef, minus half filter */
- double distance; /* dist * res. on Gaussian filter */
- long distX, distY; /* x,y dist.s within filter mask */
- double xInR, yInR; /* yIn,xIn scaled by RESOLUTION */
- long i, j; /* increment */
- long iR, jR; /* increment scaled by RESOLUTION */
- long xMinWR, yMinWR; /* min. of mask on scaled coord.s */
- double rateR; /* scaled rate */
- double sqrt (), exp (), log2 ();
- long nbrSum; /* sum of coef.s for ONs in nbrhd */
-
- /* compute filter coef.s */
- halfFltr = (fltrSize - 1) / 2;
- halfCoef = halfFltr * RESOLUTION;
- halfCoefPHalf = halfFltr * RESOLUTION + (RESOLUTION + 1) / 2;
-
- if ((coef = (long **) calloc (halfCoefPHalf + 1, sizeof (long *))) == NULL)
- exit (1);
- for (i = 0; i <= halfCoefPHalf; i++)
- if ((coef[i] = (long *) calloc (halfCoefPHalf + 1, sizeof (long))) == NULL)
- exit (1);
-
- for (i = 0; i <= halfCoefPHalf; i++) {
- exponent = ((double) (i)) / (RESOLUTION * fltrVar);
- coef[0][i] = coef[i][0]
- = (long) (MAXCOEF * exp (-exponent * exponent / 2.0) + 0.5);
- }
- for (j = 1; j <= halfCoefPHalf; j++) {
- for (i = 1; i <= halfCoefPHalf; i++) {
- distance = sqrt ((double) (i * i + j * j));
- exponent = distance / (RESOLUTION * fltrVar);
- coef[j][i] = (long) (MAXCOEF * exp (-exponent * exponent / 2.0) + 0.5);
- }
- }
-
- /* filter and subsample */
- end.x = widthIn - 1 - halfFltr;
- end.y = heightIn - 1 - halfFltr;
- endYMHalf = (double) (end.y - halfFltr);
- endXMHalf = (double) (end.x - halfFltr);
-
- yInR = halfFltr * RESOLUTION;
- rate = 100.0 / pct;
- rateR = rate * RESOLUTION;
-
- for (yIn = halfFltr, yOut = 0; yIn < endYMHalf; yIn += rate, yInR += rateR) {
- yInMid = (long) (yIn + 0.5);
- yMinW = yInMid - halfFltr;
- yMaxW = yInMid + halfFltr;
- yMinWR = yMinW * RESOLUTION;
- xInR = halfFltr * RESOLUTION;
- for (xIn = halfFltr, xOut = 0; xIn < endXMHalf; xIn += rate, xInR += rateR) {
- xInMid = (long) (xIn + 0.5);
- xMinW = xInMid - halfFltr;
- xMaxW = xInMid + halfFltr;
- xMinWR = xMinW * RESOLUTION;
- sum = sumCoef = nbrSum = 0;
- for (j = yMinW, jR = yMinWR; j <= yMaxW; j++, jR += RESOLUTION) {
- distY = (long) (ABSF (yInR - jR) + 0.5);
- for (i = xMinW, iR = xMinWR; i <= xMaxW; i++, iR += RESOLUTION) {
- distX = (long) (ABSF (xInR - iR) + 0.5);
- if (imgIn[j][i] != 0)
- sum += coef[distY][distX] * imgIn[j][i];
- sumCoef += coef[distY][distX];
- }
- }
- if (sum != 0) {
- temp = (long) ((double) sum / (threshG * sumCoef) + 0.5);
- if (temp > 255)
- temp = 255;
- imgOut[yOut][xOut++] = (unsigned char) temp;
- }
- else
- imgOut[yOut][xOut++] = 0;
- }
- yOut++;
- }
- *heightOut = yOut;
-
- return (0);
- }
-
-
- /* USAGE: function gives instructions on usage of program
- * usage: usage (flag)
- * When flag is 1, the long message is given, 0 gives short.
- */
-
- long
- usage (flag)
- short flag; /* flag =1 for long message; =0 for short message */
- {
-
- /* print short usage message or long */
- printf ("usage: subsampleNI in.img out.img\n");
- printf ("\t\t[-p PCT <%4.1f%%>] OR ([-h HEIGHT] AND/OR [-w WIDTH])\n",
- DFLTPCT);
- printf ("\t\t[-tg GRAY CONTRAST <%3.0f%%>]\n", G_THRESHPCT_M);
- printf ("\t\t[-f FLTRSIZE]\n");
- printf ("\t\t[-qf QUICK FILTER (rectangular filter)]\n");
- printf ("\t\t[-gf GAUSSIAN FILTER (instead of default matched filter]\n");
- printf ("\t\t[-v VARIANCE MULTIPLE (for Gaussian) <%2.0f>]\n", FLTR_VAR_NUM);
- if (flag == 0)
- return (-1);
-
- printf ("\nSUBSAMPLENI filters and subsamples to chosen size.\n");
- printf ("\nFLAGS:\n");
- printf ("\t-p PCT percentage size of image sidelengths to retain.\n");
- printf ("\t-h HEIGHT -w WIDTH size of image sidelengths to retain.\n");
- printf ("\t\tPCT can be used alone OR (HEIGHT AND/OR WIDTH). When both\n");
- printf ("\t\tHEIGHT and WIDTH are used, the smaller reduction is made.\n");
- printf ("\t-tg GRAY CONTRAST PCT smaller number gives darker image.\n");
- printf ("\t\tSetting -tg to 100%%, turns off constrasting.\n");
- printf ("\t-f FILTER SIZE is square mask size low-pass filter (>= 3).\n");
- printf ("\t-qf QUICK FILTER - quicker rectangular filter instead of\n");
- printf ("\t\tdefault matched filter.\n");
- printf ("\t\tIf filter size is set to 1, this is the quickest and\n");
- printf ("\t\tugliest result.\n");
- printf ("\t\tNote that this filter is used automatically instead\n");
- printf ("\t\tof default for filter sizes larger than 5x5.\n");
- printf ("\t-gf GAUSSIAN FILTER - symmetric Gaussian filter instead of\n");
- printf ("\t\tdefault matched filter.\n");
- printf ("\t-v VARIANCE MULTIPLE is no. of variances of Gaussian filter\n");
- printf ("\t\tat maximum radius in filter window (0 gives uniform wting).\n");
- printf ("\t-L: print Software License for this module\n");
-
- return (-1);
- }
-
-
- /* INPUT: function reads input parameters
- * usage: input (argc, argv, &pct, &wSize, &hSize,
- * &fltrSize, &fltrVar, &threshG,
- * &gFlag, &qfFlag, &gfFlag)
- */
-
-
- #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
-
- long
- input (argc, argv, pct, wSize, hSize, fltrSize, fltrVarNum, threshG,
- qfFlag, gfFlag)
- int argc;
- char *argv[];
- double *pct; /* subsample percentage */
- long *wSize, *hSize; /* subsampled image size: width, height */
- long *fltrSize; /* filter sidelength */
- double *fltrVarNum; /* num. of var.s at max width of fltr */
- double *threshG; /* gray-scale threshold scale factor */
- short *qfFlag; /* quick filter if =1, or default if 0 */
- short *gfFlag; /* Gaussian filter if =1, or default if 0 */
- {
- long n;
- double atof ();
-
- if (argc < 3)
- USAGE_EXIT (-1);
-
- *pct = DFLTPCT;
- *wSize = *hSize = -1;
- *fltrSize = 1;
- *threshG = -1.0;
- *fltrVarNum = FLTR_VAR_NUM;
- *qfFlag = 0;
- *gfFlag = 0;
-
- for (n = 3; n < argc; n++) {
- if (strcmp (argv[n], "-p") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *pct = atof (argv[n]);
- }
- else if (strcmp (argv[n], "-w") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *wSize = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-h") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *hSize = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-f") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *fltrSize = atol (argv[n]);
- }
- else if (strcmp (argv[n], "-tg") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *threshG = atof (argv[n]);
- }
- else if (strcmp (argv[n], "-v") == 0) {
- if (++n == argc || argv[n][0] == '-')
- USAGE_EXIT (-1);
- *fltrVarNum = atof (argv[n]);
- }
- else if (strcmp (argv[n], "-qf") == 0)
- *qfFlag = 1;
- else if (strcmp (argv[n], "-gf") == 0)
- *gfFlag = 1;
- else if (strcmp (argv[n], "-L") == 0) {
- print_sos_lic ();
- exit (0);
- }
- else
- USAGE_EXIT (-1);
- }
-
- return (0);
- }
-